// BA2.h
struct Gene
{
  string g1;
  string g2;
};

struct Indiv
{
  std::vector<Gene> genotypes;  // vector of maternal and paternal genotypes
  string sampledPopulation;        // population sampled from
  string label;                 // label for individual
};

struct AugmentIndiv
{
  int migrantPopulation;  // population of migrant ancestry
  int ancestryAge; // age of migrant ancestry
  double fstat; // inbreeding coefficient
};

class Parameters
{
 public:
  Parameters();
  string outfile;
  string logfile;
  int Ngens;
  long int MCMCreps;
  long int MCMCthin;
  long int MCMCdisplay;
  long int MCMCburnin;
  string missingData;
  string fileFormat;
  double migPropDirichlet;
  double alleleFreqDirichlet;
  double windowDelta;
  vector<string> alist;
  long int seed;
};

class BayesAss
{
 public:
  BayesAss();
  void BayesAssMCMC(Parameters pvalues, ofstream &outfile, ofstream &logfile);
 private:
  double slidingWindowProposal(double perturb, double lowerBound, double upperBound, double origValue);
  double BAlocallogL(int indiv);
  double BAlocallogL(int indiv, int aLocus);
  double BAlocallogL(int indiv, int aLocus, vector< vector< vector<double> > > modAlleleFreqs); 
  double BAlocallogL(int indiv,  vector<AugmentIndiv> proposedAugmentedSample);
  double BAlocallogL(int indiv, vector< vector< vector<double> > > modAlleleFreqs);
  double BAgloballogL();
  double BAgloballogL(int aLocus);
  double BAgloballogL(int aLocus, vector< vector< vector<double> > > modAlleleFreqs);
  double BAgloballogL(vector< vector< vector<double> > > modAlleleFreqs);
  double BAmigratelogP(Parameters pvalues);
  double BAmigratelogP(Parameters pvalues,vector< vector <double> > proposedMigrationRates);
  double BAmigratelogP(Parameters pvalues,vector< vector< vector<long int> > > proposedMigrantCounts);
  void PrintAlleleFreqs();
  vector<AugmentIndiv> augmentedSample;
  vector< vector< vector<double> > > alleleFreqs;
  vector< vector< vector<double> > > avgAlleleFreqs;
  vector< vector<double> > migrationRates;
  vector< vector<double> > avgMigrationRates;
  vector< vector<double> > m2MigrationRates;
  vector< vector< vector<long int> > > migrantCounts;
};


struct simGene
{
  int g1;
  int g2;
};

struct simIndiv
{
  std::vector<simGene> genotypes;  // vector of maternal and paternal genotypes
  int sampledPopulation;        // population sampled from
  int label;                 // label for individual
  double fstat;
};

class Simulate
{
 public:
  Simulate();
  void simulateSample();
  void PrintAlleleFreqs();
  void PrintMigrantAncestries();
 private:
  vector<long int> sampleSizes;
  vector< vector<double> > avgAlleleFreqs;
  vector< vector< vector<double> > > simAlleleFreqs;
  vector< vector<double> > simMigrationRates;
  long int simSeed;
  vector<vector <int> > migrantAncestry;
  vector<vector <int> > ancestryAge;
  vector<simIndiv> simulatedSample;
};

void DataSummary(Parameters pvalues);
int TranslateCommand(string cmd);
void PrintBanner();
void PrintCommands();
void ReadData(ifstream &infile, Parameters &pvalues);
void PrintParameters(Parameters pvalues);
int SetParameters(Parameters &pvalues);
void PrintData(string filename);
void GetAlleleCounts(Parameters pvalues);
void PrintAlleleCounts(Parameters pvalues);
double logGenotypeProbability(int indiv, int popln, vector< vector< vector<long int> > > ExAlleleCounts);
double BayesianAssignment(int indiv, int popln,	vector< vector< vector<long int> > > ExAlleleCounts);
void Bat(Parameters pvalues);
void sset();
void PrintSimulationParameters();




